﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using iWare.Wms.Core.Entity.Receiving;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;

namespace iWare.Wms.Application
{
    /// <summary>
    /// LES送货单服务
    /// </summary>
    [Route("api/LESGoodsDelivery")]
    [ApiDescriptionSettings("LES供应商模块", Name = "LESGoodsDelivery", Order = 102)]

    public class LESGoodsDeliveryService : IDynamicApiController, ITransient
    {
        private readonly ISqlRepository<ERPDbContextLocator> _erpRep;
        private readonly IRepository<WareDictData, MasterDbContextLocator> _wareDictDataRep; //仓库字典值仓储
        private readonly IRepository<PurchaseOrder, MasterDbContextLocator> _purchaseOrderRep; //采购订单仓储
        private readonly IRepository<GoodsDelivery, MasterDbContextLocator> _goodsDeliveryRep; //送货单仓储
        private readonly IRepository<GoodsDeliveryDetails, MasterDbContextLocator> _goodsDeliveryDetailsRep; //送货单明细仓储
        private readonly IRepository<GoodsDeliveryTagPrint, MasterDbContextLocator> _goodsDeliveryTagPrintRep; //送货标签打印仓储
        private readonly IRepository<SupplierExamineFlower, MasterDbContextLocator> _supplierExamineFlowerRep; //送货单审核记录仓储

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="erpRep"></param>
        /// <param name="wareDictDataRep"></param>
        /// <param name="purchaseOrderRep"></param>
        /// <param name="goodsDeliveryRep"></param>
        /// <param name="goodsDeliveryDetailsRep"></param>
        /// <param name="goodsDeliveryTagPrintRep"></param>
        /// <param name="supplierExamineFlowerRep"></param>
        public LESGoodsDeliveryService(
            ISqlRepository<ERPDbContextLocator> erpRep,
            IRepository<WareDictData, MasterDbContextLocator> wareDictDataRep,
            IRepository<PurchaseOrder, MasterDbContextLocator> purchaseOrderRep,
            IRepository<GoodsDelivery, MasterDbContextLocator> goodsDeliveryRep,
            IRepository<GoodsDeliveryDetails, MasterDbContextLocator> goodsDeliveryDetailsRep,
            IRepository<GoodsDeliveryTagPrint, MasterDbContextLocator> goodsDeliveryTagPrintRep,
            IRepository<SupplierExamineFlower, MasterDbContextLocator> supplierExamineFlowerRep
        )
        {
            _erpRep = erpRep;
            _wareDictDataRep = wareDictDataRep;
            _purchaseOrderRep = purchaseOrderRep;
            _goodsDeliveryRep = goodsDeliveryRep;
            _goodsDeliveryDetailsRep = goodsDeliveryDetailsRep;
            _goodsDeliveryTagPrintRep = goodsDeliveryTagPrintRep;
            _supplierExamineFlowerRep = supplierExamineFlowerRep;
        }
        #endregion

        /// <summary>
        /// 分页查询LES送货单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("Page")]
        public async Task<PageResult<LESGoodsDeliveryOutput>> Page([FromQuery] LESGoodsDeliveryInput input)
        {
            var statelist = new List<AuditStatusEnum> { AuditStatusEnum.yuyuezhong, AuditStatusEnum.yuyuechenggong, AuditStatusEnum.shenhezhong, AuditStatusEnum.bohui, AuditStatusEnum.shenhetongguo, AuditStatusEnum.songhuozhong, AuditStatusEnum.songhuowancheng };

            var goodsDelivery = await _goodsDeliveryRep.DetachedEntities
                .Where(input.IsJiaJiJian != null && input.IsJiaJiJian != YesOrNot.All, u => u.IsJiaJiJian == input.IsJiaJiJian)
                .Where(statelist.Contains(input.Status), p => p.Status == input.Status)
                .Where(!string.IsNullOrEmpty(input.PurchaseNo), u => EF.Functions.Like(u.PurchaseNo, $"%{input.PurchaseNo.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.DeliveryNo), u => EF.Functions.Like(u.DeliveryNo, $"%{input.DeliveryNo.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.DeliveryType), u => EF.Functions.Like(u.DeliveryType, $"%{input.DeliveryType.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.ProjectCode), u => EF.Functions.Like(u.ProjectCode, $"%{input.ProjectCode.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.SuppName), u => EF.Functions.Like(u.SuppName, $"%{input.SuppName.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.SearchBeginTime), u => u.GoodsDeliveryAppointments.DeliverDate >= DateTime.Parse(input.SearchBeginTime.Trim()) &&
                 u.GoodsDeliveryAppointments.EstimatedDate <= DateTime.Parse(input.SearchEndTime.Trim()))
                //.OrderBy(PageInputOrder.OrderBuilder(input.Status == AuditStatusEnum.shenhezhong))
                .OrderByDescending(z => z.Status == AuditStatusEnum.shenhezhong)
                .ThenByDescending(z => z.CreatedTime)
                .ProjectToType<LESGoodsDeliveryOutput>()
                .ToADPagedListAsync(input.PageNo, input.PageSize);

            foreach (var item in goodsDelivery.Rows)
            {
                if (item.GoodsDeliveryAppointments != null)
                {
                    if (!string.IsNullOrEmpty(item.GoodsDeliveryAppointments.Images) && item.GoodsDeliveryAppointments.Images != "N/A")
                    {
                        var imageList = item.GoodsDeliveryAppointments.Images.Split(',');

                        if (imageList.Count() > 1)
                        {
                            var list = new List<long>();
                            foreach (var image in imageList)
                            {
                                list.Add(Convert.ToInt64(image));
                            }
                            item.GoodsDeliveryAppointments.ImagesList = list;
                        }
                        else
                        {
                            var list = new List<long>();
                            list.Add(Convert.ToInt64(item.GoodsDeliveryAppointments.Images));
                            item.GoodsDeliveryAppointments.ImagesList = list;
                        }
                    }
                    else if (item.GoodsDeliveryAppointments.Images != "N/A")
                    {
                        var list = new List<long>();
                        list.Add(Convert.ToInt64(item.GoodsDeliveryAppointments.Images));
                        item.GoodsDeliveryAppointments.ImagesList = list;
                    }
                    else
                    {
                        item.GoodsDeliveryAppointments.ImagesList = null;
                    }
                }

                var purchaseOrder = await _purchaseOrderRep.Where(t => t.PurchaseNo.Equals(item.PurchaseNo)
                && t.PurchaseType.Equals(item.DeliveryType)).FirstOrDefaultAsync();
                item.PurchaseNo = item.IsJiaJiJian == YesOrNot.Y ? "" : item.PurchaseNo;
                item.DeliveryType = (await _wareDictDataRep.FirstOrDefaultAsync(z => z.Code == purchaseOrder.PurchaseType)).Value;
                item.QuantityTotal = (await _goodsDeliveryDetailsRep.DetachedEntities.Where(z => z.GoodsDelivery.DeliveryNo == item.DeliveryNo).ToListAsync())
                    .Sum(t => t.DeliveryQuantity);
            }

            return goodsDelivery;
        }

        /// <summary>
        /// 分页查询LES送货单明细
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("DetailPage")]
        public async Task<List<GoodsDeliveryDetailsOutput>> DetailPage([FromQuery] GoodsDeliveryDetailsSearch input)
        {
            var goodsDeliveryDetailss = await _goodsDeliveryDetailsRep.DetachedEntities
                .Where(input.GoodsDeliveryId != null, u => u.GoodsDeliveryId == input.GoodsDeliveryId)
                .Where(!string.IsNullOrEmpty(input.Code), u => u.Code == input.Code)
                .Where(!string.IsNullOrEmpty(input.Name), u => u.Name == input.Name)
                .OrderBy(t => t.XuHao)
                .ProjectToType<GoodsDeliveryDetailsOutput>()
                .ToListAsync();

            var ProjectModel = await _goodsDeliveryRep
                .Where(n => n.Id == input.GoodsDeliveryId).FirstOrDefaultAsync();

            var goodsDelivery = await _goodsDeliveryRep.FirstOrDefaultAsync(n => n.Id == input.GoodsDeliveryId);

            foreach (var item in goodsDeliveryDetailss)
            {
                item.ProjectCode = ProjectModel.ProjectCode;
                item.CreatedTime = ProjectModel.CreatedTime;
                item.BrandName = string.IsNullOrEmpty(item.BrandName) || item.BrandName == "无" ? "" : item.BrandName;
                var goodsDeliveryTagPrint = await _goodsDeliveryTagPrintRep.FirstOrDefaultAsync(z => z.GoodsDeliveryId == item.GoodsDeliveryId
                     && z.ProjectCode == item.ProjectCode && z.Code == item.Code);
                item.DeliveryNo = goodsDelivery.DeliveryNo;
            }

            return goodsDeliveryDetailss;
        }

        /// <summary>
        /// 通过送货预约信息
        /// </summary>
        /// <returns></returns>
        [HttpPost("AdoptGoodsDelivery")]
        //[UnitOfWork]
        public async Task AdoptGoodsDeliveryAppointment(SubmitGoodsDeliveryAppointmentInput input)
        {
            //更新送单号的信息的状态
            var deliveryModel = await _goodsDeliveryRep.SingleAsync(u => u.Id == input.DeliveryID && u.DeliveryNo == input.DeliveryNo, true);

            #region 最新要求（管理员审核通过后直接发货，不用供应商再点送货。）
            deliveryModel.Status = AuditStatusEnum.songhuozhong;//.shenhetongguo; //审核通过送货中
            #endregion

            deliveryModel.UpdatedTime = DateTimeOffset.Now;
            await _goodsDeliveryRep.UpdateAsync(deliveryModel);

            //创建一条审批记录
            var supplierExaminerFlowerModel = new SupplierExamineFlower()
            {
                Status = AuditStatusEnum.songhuozhong,//.shenhetongguo, //送货中
                DeliveryID = deliveryModel.Id,
                Remarks = "送货中"
            };
            await _supplierExamineFlowerRep.InsertAsync(supplierExaminerFlowerModel);
        }

        /// <summary>
        /// 驳回送货预约信息
        /// </summary>
        /// <returns></returns>
        [HttpPost("RejectGoodsDelivery")]
        //[UnitOfWork]
        public async Task RejectGoodsDeliveryAppointment(RejectGoodsDeliveryAppointmentInput input)
        {
            //更新送单号的信息的状态
            var deliveryModel = await _goodsDeliveryRep.SingleAsync(u => u.Id == input.DeliveryID && u.DeliveryNo == input.DeliveryNo, true);

            deliveryModel.Status = AuditStatusEnum.bohui; //驳回中

            await _goodsDeliveryRep.UpdateAsync(deliveryModel);

            //创建一条审批记录
            var supplierExaminerFlowerModel = new SupplierExamineFlower()
            {
                Status = AuditStatusEnum.bohui, //驳回
                DeliveryID = deliveryModel.Id,
                Remarks = "驳回,驳回原因[" + input.Remarks + "]"
            };
            await _supplierExamineFlowerRep.InsertAsync(supplierExaminerFlowerModel);
        }

        /// <summary>
        /// 打印送货单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("Print")]
        public async Task<GoodsDeliveryOutput> Print([FromQuery] PrintGoodsDeliveryInput input)
        {
            var model = (await _goodsDeliveryRep.DetachedEntities.Where(u => u.Id == input.DeliveryID)
                .ProjectToType<GoodsDeliveryOutput>().FirstOrDefaultAsync());

            if (model != null)
            {
                var purchaseOrder = await _purchaseOrderRep
                    .FirstOrDefaultAsync(z => z.PurchaseNo == model.PurchaseNo && z.SupplierInfoCode == model.SuppCode);
                var wareDictData = await _wareDictDataRep
                    .FirstOrDefaultAsync(z => z.Code == purchaseOrder.PurchaserUserId);

                model.PurchaseNo = purchaseOrder.IsJiaJiJian == YesOrNot.Y ? "" : purchaseOrder.PurchaseNo;
                model.ReceUser = wareDictData == null ? "" : wareDictData.Value;

                var deliveryDetailsList = model.GoodsDeliveryDetails.OrderBy(t => t.XuHao);
                foreach (var item in deliveryDetailsList)
                {
                    item.DeliveryNo = model.DeliveryNo;
                    item.BrandName = string.IsNullOrEmpty(item.BrandName) || item.BrandName == "无" ? "" : item.BrandName;
                }
                return model;
            }
            else return null;
        }

        /// <summary>
        /// 更新送货单状态为“送货完成”
        /// </summary>
        /// <returns></returns>
        [HttpPost("EditStatus")]
        public async Task EditStatus([FromBody] EditStatusInput input)
        {
            var goodsDelivery = await _goodsDeliveryRep.FirstOrDefaultAsync(z => z.Id == input.GoodsDeliveryId && z.DeliveryNo == input.DeliveryNo);
            if (goodsDelivery == null) throw Oops.Oh("送货单信息不存在!");

            var purchaseOrder = await _purchaseOrderRep.FirstOrDefaultAsync(z => z.PurchaseNo == goodsDelivery.PurchaseNo);
            if (purchaseOrder != null)
            {
                var purtcOutputList = await _erpRep
                .SqlQueryAsync<PURTCOutput>
                (@"select TC001,  --采购单别
                              TC002,  --采购单号
                              TC003,  --采购日期
                              TC004,  --供应商
                              TC009,  --备注
                              TC011,  --采购人员
                              TC023,  --数量合计
                              TC047,  --项目编号
                              UDF01,  --收货地址
                              TC030,  --签核状态码  0.待处理、S.传送中、1.签核中、2.退件、3.已核准、4.撤销审核中、5.作废中、6.取消作废中、N.不运行电子签核
                              TCD01   --是否结束 N:未结束、Y:结束 [DEF:""N""]
                       from PURTC where TC002='" + purchaseOrder.PurchaseNo + "' and TC001='" + purchaseOrder.PurchaseType + "' and TC047='" + purchaseOrder.ProjectCode + "'");

                foreach (var itemDetail in purtcOutputList)
                {
                    if (itemDetail.TCD01 != "Y") throw Oops.Oh("ERP对应的采购单未结束");

                    if (itemDetail.TCD01 == "Y")
                    {
                        goodsDelivery.Status = input.Status;
                        await _goodsDeliveryRep.UpdateAsync(goodsDelivery);
                    }
                }
            }
        }
    }
}
